package Runde7;

public class TransportAnhaenger {

	private final AnhaengeKopplung[] aKopplung;
	private final Abteil[][] abteile;
	
	/**
	 * @precondition gw.length <= aSize, gw != null
	 * @postcondition creates a new instance of TransportAnhaenger with given amount of compartments, "anhaengekopplungen" and big game (groszwild)
	 */
	//WasserSize, LandwasserSize, TMambaSize, TPython, TZwergSize, tRiesenSize, anhaengeSize, Groszwild[] 
	public TransportAnhaenger(int wSize, int lwSize, int tmSize, int tpSize, int tzSize, int trSize, int aSize, Groszwild[] gw) {
		
		abteile = new Abteil[6][];
		
		abteile[0] = new Wassertank[wSize];
		for (int i = 0; i < wSize; i++) {
			abteile[0][i] = new Wassertank();
		}
		
		abteile[1] = new LandWassertank[lwSize];
		for (int i = 0; i < lwSize; i++) {
			abteile[1][i] = new LandWassertank();
		}
		
		abteile[2] = new TerrariumMamba[tmSize];
		for (int i = 0; i < tmSize; i++) {
			abteile[2][i] = new TerrariumMamba();
		}
		
		abteile[3] = new TerrariumPython[tpSize];
		for (int i = 0; i < tpSize; i++) {
			abteile[3][i] = new TerrariumPython();
		}
		
		abteile[4] = new TerrariumZwergschildkroete[tzSize];
		for (int i = 0; i < tzSize; i++) {
			abteile[4][i] = new TerrariumZwergschildkroete();
		}
		
		abteile[5] = new TerrariumRiesenschildkroete[trSize];
		for (int i = 0; i < trSize; i++) {
			abteile[5][i] = new TerrariumRiesenschildkroete();
		}
		
		aKopplung = new AnhaengeKopplung[aSize];
		for (int i = 0; i < gw.length; i++) {
			aKopplung[i] = new AnhaengeKopplung(gw[i]);
		}
		
	}
	
	/**
	 * @precondition t != null
	 * @postcondition loads given TransportAnhaenger on free AnhaengeKopplung, if any
	 * 		returns true or false whether operation was successful, or not
	 */
	public boolean load (TransportAnhaenger t) {
		
		for (int i = 0; i < aKopplung.length; i++) {
			if (aKopplung[i] == null) {
				aKopplung[i] = new AnhaengeKopplung(t);
				return true;
			}
		}
		return false;
	}
	
	/**
	 * @precondition t != null
	 * @postcondition loads given TransportierbaresTier to free, compatible kind of containment, if any
	 * 		returns true or false whether operation was successful, or not
	 */
	public boolean load (TransportierbaresTier t) {
		
		for (int i = 0; i < abteile.length; i++) {
			for (int j = 0; j < abteile[i].length; j++) {
				if (abteile[i][j].abtLoad(t) != null) {
					return true;
				}
			}
		}
		return false;
	}
	
	/**
	 * @precondition katIndex <= abteile[katIndex].length; index <= abteile[katIndex][index].length
	 * @postcondition unload and returns loaded TransportierbaresTier of contaiment with given index and katIndex
	 */
	public TransportierbaresTier unload(int katIndex, int index) {
		return abteile[katIndex][index].abtUnload();
	}
	
	/**
	 * @precondition index <= aKopplung.length
	 * @postcondition unload and returns loaded TransportAnhaenger of AnhaengeKopplung with given index
	 */
	public TransportAnhaenger unload(int index) {
		TransportAnhaenger temp = aKopplung[index].getTransportAnhaenger();
		aKopplung[index] = null;
		return temp;
	}
	
	/**
	 * @postcondition Returns a list of all the animals on the vehicle.
	 */
	public String list() {
		//Erst die eigenen Abteile ausgeben...
		String output = "";
		for (int i = 0; i < abteile.length; i++) {
			for (int j = 0; j < abteile[i].length; j++) {

				output += abteile[i][j].toString() + "\n";
			}
		}
		
		//und dann alles, was an den Wagen gekoppelt ist (neue Anhaenger rekursiv).
		for (int i = 0; i < aKopplung.length; i++) {
		if (aKopplung[i] != null) {			
				Groszwild tempwild = aKopplung[i].getGroszwild();				
				if (tempwild != null) {
					output += tempwild + "\n";
				} else {
					output += aKopplung[i].safeGetTransportAnhaenger().list();
				}
			}
		}
		output = output.replaceAll("null\n","");
		return output;
	}
	

	//AnhaengeKopplung-Klasse
	private class AnhaengeKopplung {
		private final Groszwild g;
		private final TransportAnhaenger t;
		private final TransportAnhaenger safeT;
		
		/**
		 * @precondition g != null
		 * @postcondition Creates new AnhaengeKopplung with given Groszwild as trailed element
		 */
		public AnhaengeKopplung(Groszwild g) {
			this.g = g;
			this.t = null;
			this.safeT = new TransportAnhaenger(0, 0, 0, 0, 0, 0, 0, new Groszwild[0]);
		} 
		
		/**
		 * @precondition t != null
		 * @postcondition Creates new AnhaengeKopplung with given TransportAnhaenger as trailed element
		 */
		public AnhaengeKopplung(TransportAnhaenger t) {
			this.t = t;
			this.g = null;
			this.safeT = this.t;
		}
		
		/**
		 * @postcondition Returns trailed Groszwild, null if this object was instanced with TransportAnhaenger as param
		 */
		public Groszwild getGroszwild() {
			return g;
		}
		
		/**
		 * @postcondition Returns trailed TransportAnhaenger, null if this object was instanced with Groszwild as param
		 */
		public TransportAnhaenger getTransportAnhaenger() {
			return t;
		}
		
		/**
		 * @postcondition Returns a safely accessible instance (never NULL) of TransportAnhaenger:
		 * 				t - if this object was instanced with TransportAnhaenger as param
		 * 				safeT (empty dummy-TransportAnhaenger) - if this object was instanced with Groszwild as param
		 */
		public TransportAnhaenger safeGetTransportAnhaenger() {
			return safeT;
		}
		
	}
	
	
}
